package com.udi.project.business.activate.service.impl;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.udi.project.business.activate.daomain.ActivateCode;
import com.udi.project.business.activate.mapper.ActivateCodeMapper;
import com.udi.project.business.activate.service.ActivateCodeService;
import com.udi.project.business.utils.RSA.RSAUtils;
import com.udi.project.business.utils.redis.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.crypto.BadPaddingException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;


/**
 * @author Admin
 * 产品激活码认证业务层
 */
@Service
public class ActivateCodeServiceImpl implements ActivateCodeService {


    /** RSA解密*/
    @Autowired
    private RSAUtils rsaUtils;
    @Autowired
    private ActivateCodeMapper activateCodeMapper;
    @Autowired
    private RedisUtils redisUtils;


    /**
    *
     * @Description:
     * @param code 激活码
     * @param key 密钥
     * @param type 密钥类型 此激活码由公钥解密还是私钥解密
     * @return: java.lang.String
     * @Date: 2021/8/23 16:57
     *  产品激活码示例：
     *      startData：激活码有效期 精确到分钟 【激活码2小时内有效】
     *      effectiveData: 产品有效期
     *      userName: 用户名【Shiro解开冻结用户，还原密码】
     *      serial：防止用户篡改时间 导致激活码重复使用  对激活码有效期的二次加密
     *      {"startData":"xxxx-xx-xx xx:xx:xx","effectiveData":"xxxx-xx-xx,"userName":"xxxxx","serial":"1177"}
     *
     * 认证步骤：
     *      拿到激活码和密钥，判断密钥类型，由RSA解密，解密完成的数据转换为JSON，
     *      拿到：激活码有效期，产品有效期，用户名，密钥类型。
     *      1、判断激活码有效期是否到期
     *      2、产品有效期加密到数据库，并保存私钥与公钥
     *
     */
    @Override
    public String certification(String code,String key,String type) throws Exception {

        SimpleDateFormat dfs = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String keyJson = null;
        ActivateCode activateCode = new ActivateCode();

        //判断密钥类型 公钥解密
        if("publicKey".equals(type)){
            activateCode.setActivation_encryption_type("privateKey");
            activateCode.setActivation_privateKey(key);
            try {
               keyJson =  rsaUtils.publicDecrypt(code,key);
            }catch (BadPaddingException e){
                e.printStackTrace();
                return "激活码错误,请检查激活码是否正确";
            }catch (InvalidKeySpecException e){
                return "密钥错误，请检查密钥类型或密钥是否正确";
            }catch (Exception e){
                e.printStackTrace();
                return "认证错误，请联系技术人员";
            }

            /** 私钥解密*/
        }else if("privateKey".equals(type)){
            activateCode.setActivation_encryption_type("publicKey");
            activateCode.setActivation_publicKey(key);
            try {
                keyJson =  rsaUtils.privateDecrypt(code,key);
            }catch (BadPaddingException e){
                e.printStackTrace();
                return "激活码错误,请检查激活码是否正确";
            }catch (InvalidKeySpecException e){
                return "密钥错误，请检查密钥类型或密钥是否正确";
            }catch (Exception e){
                e.printStackTrace();
                return "认证错误，请联系技术人员";
            }
        }

        /** 日期计算 当前日期的前2小时是否是激活码的生成时间 格式：yyyy-MM-dd HH:mm:ss*/
        JSONObject jsonObject =null;
        try {
            jsonObject = JSONObject.parseObject(keyJson);
        }catch (JSONException e){
            e.printStackTrace();
            return "你的产品激活码有误，请联系派发人员";
        }


        if(jsonObject.getString("startData") == null && jsonObject.getString("effectiveData") == null &&
                jsonObject.getString("userName") == null && jsonObject.getString("serial") == null ){
            return "你的产品激活码有误";
        }

        String num  =  activateCodeMapper.selectSerial(jsonObject.getString("serial"));
        if(num != null){
            return "激活码已使用过";
        }


            Date begin=dfs.parse(jsonObject.getString("startData"));
            Date end = new Date(System.currentTimeMillis());
            long between=(end.getTime()-begin.getTime())/1000;

            //判断当前日期与激活码日期相差天数是否等于0天
            if(between/(24*3600) == 0){
                //判断是否超过2小时
                if(between%(24*3600)/3600 <2 ){
                    String userName = jsonObject.getString("userName");
                    if(activateCodeMapper.selectUserName(userName).equals(userName)){
                        //取消冻结用户
                        activateCodeMapper.updateUser();
                        //还原当前用户密码
                        //activateCodeMapper.updatePass((String) redisUtils.get("userName"),userName);
                        //持久化有效期 激活码 加密方式等
                        activateCode.setActivation_code(code);
                        //生成公钥私钥并加密有效期
                        Map<String,String> effectiveKey = rsaUtils.generateKeyPair();
                        String privaKey = null;
                        String publiKey = null;
                        for(Map.Entry<String,String>entry:effectiveKey.entrySet()){
                            publiKey = entry.getKey();
                            privaKey = entry.getValue();
                        }
                        String data =  rsaUtils.publicEncrpyt(jsonObject.getString("effectiveData"),publiKey);
                        activateCode.setValid_period(data);
                        activateCode.setValid_privateKey(privaKey);
                        activateCode.setValid_publicKey(publiKey);
                        //有效期加密类型：公钥加密  私钥解密
                        activateCode.setValid_encryption_type("publicKey");
                        activateCode.setSerial(jsonObject.getString("serial"));
                        activateCodeMapper.insertEffectiveData(activateCode);
                    }else {return "此激活码无效";}
                }else {return "你的激活码已到期,请重新获取";}
            }else {return "你的激活码已到期,请重新获取";}
            redisUtils.set("period","no");
           return "激活成功";
    }
}
